package cn.common.exception;
import cn.common.result.Response;
import com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ConnectTimeoutException;
import feign.RetryableException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.net.SocketTimeoutException;
import java.sql.SQLException;

@ControllerAdvice
@ResponseBody
public class DefaultExceptionAdvice {
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionAdvice.class);
    /**
     * BusinessException 业务异常处理
     * @return ResponseEntity
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Response> handleException(BusinessException e) {
        System.out.println("BusinessException");
        LOGGER.error("业务异常", e);
        Response response = Response.Failure(e.getError());
        return new ResponseEntity<>(response, HttpStatus.OK);
    }
//    @ExceptionHandler(RetryableException.class)
//    public ResponseEntity<Response> handleFeignTimeout(RetryableException e) {
//        Throwable cause = e.getCause();
//        if (cause instanceof SocketTimeoutException) {
//            return handleSocketTimeout((SocketTimeoutException) cause);
//        }
//        return null;
//    }
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    @ExceptionHandler(SocketTimeoutException.class)
    public ResponseEntity<Response> handleSocketTimeout(SocketTimeoutException e) {
        Response response = Response.Failure(DefaultError.TIMEOUT_EXCEPTION);
        response.setResult(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.GATEWAY_TIMEOUT);
    }
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    @ExceptionHandler(ConnectTimeoutException.class)
    public ResponseEntity<Response> handleConnectTimeoutException(ConnectTimeoutException e) {
        Response response = Response.Failure(DefaultError.TIMEOUT_EXCEPTION);
        response.setResult(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.GATEWAY_TIMEOUT);
    }
//    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
//    @ExceptionHandler(SocketTimeoutException.class)
//    public ResponseEntity<Response> handleException(TimeOutException e) {
//        System.out.println("TimeOutException");
//        LOGGER.error("远程请求异常", e);
//        Response response = Response.Failure(e.getError());
//        return new ResponseEntity<>(response, HttpStatus.OK);
//    }

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(TokenException.class)
    public ResponseEntity<Response> handleTokenException(TokenException e) {
        LOGGER.error("token异常", e);
        Response response = Response.Failure(e.getError());
        return new ResponseEntity<>(response, HttpStatus.OK);
    }
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    public ResponseEntity<Response> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        LOGGER.error("不支持当前媒体类型", e);
        Response response = Response.Failure(DefaultError.CONTENT_TYPE_NOT_SUPPORT);
        response.setResult(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.UNSUPPORTED_MEDIA_TYPE);
    }
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public ResponseEntity<Response> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        LOGGER.error("不支持当前请求方法", e);
        Response response = Response.Failure(DefaultError.METHOD_NOT_SUPPORTED);
        response.setResult(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.METHOD_NOT_ALLOWED);
    }
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({
            HttpMessageNotReadableException.class,
            MissingServletRequestParameterException.class
    })
    public ResponseEntity<Response> handleBadRequest(Exception e) {
        Response response = new Response();

        if (e instanceof HttpMessageNotReadableException) {
            LOGGER.error(" 请求体解析异常", e);
            response = Response.Failure(DefaultError.INVALID_PARAMETER);
            response.setResult(" 请求数据格式错误");
        }
        else if (e instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException ex = (MissingServletRequestParameterException) e;
            LOGGER.error(" 缺少必要参数: {}", ex.getParameterName());
            response = Response.Failure(DefaultError.MISSING_PARAM);
            response.setResult(" 必需参数: " + ex.getParameterName());
        }

        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({SQLException.class,NullPointerException.class})
    public ResponseEntity<Response> handleSQLException(Exception e) {
        Response response = new Response();
        if (e instanceof SQLException) {
            LOGGER.error("服务运行SQLException异常", e);
            response = Response.Failure(DefaultError.INVALID_PARAMETER);
            response.setResult(" 请求数据格式错误");
        }
        else if (e instanceof NullPointerException) {
            LOGGER.error("空指针异常:", e);
            response = Response.Failure(DefaultError.NULL_EXCEPTION);
            response.setResult(e.getMessage());
        }
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }


}
